#pragma once
#include <iostream>
#include <assert.h>
#include <thread>
#include <mutex>
#include <algorithm>
#include <unordered_map>
#include <vector>
using std::endl;
using std::cout;
#ifdef _WIN64
	typedef unsigned long long Page_ID;
	#include <windows.h>
#elif _WIN32
	#include <windows.h>
	typedef size_t Page_ID;
#endif

static const size_t max_size = 256 * 1024;
static const size_t nfreelist = 208;
static const size_t npages = 129;
static const size_t page_shift = 13;//小于等于16，因为VirtualAlloc是按64KB分配粒度对齐的（分配粒度对齐）

template<class t>
class objectpool//注意这是一个定长内存池，也就是存放的类型都是t
{
private:
	char* _mempool = nullptr;
	void** _freelist = nullptr;
	size_t _left = 0;
public:
	t* New()
	{
		t* obj = nullptr;
		//优先利用还回来的空间
		if (_freelist)
		{
			obj = (t*)_freelist;
			_freelist = (void**)(*_freelist);
		}
		else
		{
			if (_left < sizeof(t))
			{
				_mempool = (char*)VirtualAlloc(0, 6 * (1<<13), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
				if (_mempool == nullptr)
					throw std::bad_alloc();
				_left = 6 * (1<<13);
			}
			obj = (t*)_mempool;
			size_t objsize = sizeof(t) < sizeof(void*) ? sizeof(void*) : sizeof(t);//创建的对象大小小于一个指针的大小，也就存不下下一个释放空间得到地址了，那么就将new的空间给一个地址所需空间这么大
			_mempool += objsize;	 
			_left -= objsize;
		}
		new(obj)t;//使用定位new初始化这段空间
		return obj;
	}
	void Delete(t* obj)//将删除的部分头插到_freelist中
	{
		obj->~t();//显示调用析构函数，注意该析构函数析构的是对象本身而不是释放这段空间，释放空间的操作还是下面的代码，也就是使用我们自己写的delete可以将对象析构并释放空间
		*((void**)obj) = _freelist;
		_freelist = (void**)obj;
	}
};
